using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Web;

using IGlobalist.Cms.Model;


namespace IGlobalist.Cms.Bll
{
   
    public class CategoryXMLCtr : BaseController
    {
        private static string categoryFilePath = "Admin\\XML\\Categories.xml";
        private static XmlDocument xDoc;
        private static IList<CategoryXML> categories;
        static CategoryXMLCtr()
        {
             categoryFilePath = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, categoryFilePath);
        }

        public static CategoryXML GetCategoryByID(long id){

            XmlNode xNode = GetXmlNodeByID(id);
            return Convert2Category(xNode);
        }

        

        public static IContentCategory GetContentCategoryByID(long id)
        {
            LoadXML();
            try
            {
                XmlNode xNode = GetXmlNodeByID(id);
                CategoryXML cat = Convert2Category(xNode);
                IContentCategory c = new Category();
                c.Name = cat.Name;
                c.ID = cat.Id;
                c.ParentID = cat.Parent;
                c.Description = cat.Description;
                return c;
            }
            catch (Exception ex)
            {
                Logger.Error("", ex);
            }
            return null;
        }

        private static XmlNode GetXmlNodeByID(long id)
        {
            LoadXML();
            string xpath = String.Format("//Category[@id='{0}']",id);
            XmlNode xNode = xDoc.DocumentElement.SelectSingleNode(xpath);
            return xNode;
        }

        public static IList<CategoryXML> ListHomepage()
        {
            IList<CategoryXML> list = new List<CategoryXML>();
            LoadXML();
            try
            {
                string xpath = "//Category[@type='1']";
                XmlNodeList xNodes = xDoc.SelectNodes(xpath);
                foreach (XmlNode xNode in xNodes)
                {
                    CategoryXML cat = Convert2Category(xNode);
                    if (cat != null)
                        list.Add(cat);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("ListHomepage ::", ex);
            }
            return list;
        }

        public static IList<CategoryXML> List()
        {
            IList<CategoryXML> list = new List<CategoryXML>();
            LoadXML();
            try
            {
                string xpath = "//Category[@type='0']";
                XmlNodeList xNodes = xDoc.SelectNodes(xpath);
                foreach (XmlNode xNode in xNodes)
                {
                    CategoryXML cat = Convert2Category(xNode);
                    if (cat != null)
                        list.Add(cat);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("ListHomepage ::", ex);
            }
            return list;
        }

        public static void Add(CategoryXML category)
        {
            try
            {

                XmlElement xNode = xDoc.CreateElement("Category");
                xNode.SetAttribute("id", category.Id.ToString());
                xNode.SetAttribute("name", category.Name);
                xNode.SetAttribute("description", category.Description);
                xNode.SetAttribute("url", category.Url);
                xNode.SetAttribute("parent", category.Parent.ToString());
                xNode.SetAttribute("subs", "");
                xNode.SetAttribute("type","0");
                
                xDoc.DocumentElement.AppendChild(xNode);
                Save();
            }
            catch (Exception ex)
            {
                Logger.Error("", ex);
            }
        }


        public static void AddSub(CategoryXML category, IList<long> subListIDs)
        {
            category.Subs = new List<long>();
            foreach (long Id in subListIDs)
            {
                if (!category.Subs.Contains(Id))
                    category.Subs.Add(Id);
            }
            Update(category);
        }

        public static void AddSub(long categoryID, IList<long> subListIDs)
        {
            CategoryXML category = GetCategoryByID(categoryID);
            AddSub(category, subListIDs);
        }

        public static void RemoveSub(CategoryXML category, long removeSubID)
        {
            try
            {
                category.Subs.Remove(removeSubID);
                Update(category);
            }
            catch (Exception ex)
            {
                Logger.Error("", ex);
            }
            
        }

        public static void Remove(long categoryID)
        {
            try
            {
                XmlNode xNode = GetXmlNodeByID(categoryID);
                if (xNode != null)
                {
                    xDoc.DocumentElement.RemoveChild(xNode);
                    Save();
                    List();
                }
            }
            catch (Exception ex)
            {
                Logger.Error("", ex);
            }
        }
        
        public static void RemoveSub(long categoryID, long removeSubID)
        {
            CategoryXML category = GetCategoryByID(categoryID);
            try
            {
                category.Subs.Remove(removeSubID);
                Update(category);
            }
            catch (Exception ex)
            {
                Logger.Error("", ex);
            }
           
        }

        public static void Save()
        {
            lock (xDoc)
            {
                xDoc.Save(categoryFilePath);
            }
        }

        public static void Update(CategoryXML category)
        {
            try
            {
                XmlNode xNode = GetXmlNodeByID(category.Id);
                xNode.Attributes["name"].Value = category.Name;
                xNode.Attributes["description"].Value = category.Description;
                xNode.Attributes["url"].Value = category.Url;
                xNode.Attributes["parent"].Value = category.Parent.ToString();
                xNode.Attributes["subs"].Value = SubList2StringSub(category.Subs);
                Save();
            }
            catch (Exception ex)
            {
                Logger.Error("", ex);
            }
        }


        

        public int IndexOf(CategoryXML category)
        {
            int index = -1;
            int i = 0;
            foreach (CategoryXML cat in categories)
            {
                if (cat.Id == category.Id)
                {
                    index = i;
                }
                i++;
            }
            return index;
        }

        public int IndexOf(long  categoryID)
        {
            int index = -1;
            int i = 0;
            foreach (CategoryXML cat in categories)
            {
                if (cat.Id == categoryID)
                {
                    index = i;
                }
                i++;
            }
            return index;
        }

        

        #region "Method Member Private"

        public static IList<CategoryXML> ListAll()
        {
            categories = new List<CategoryXML>();
            LoadXML();
            try
            {
                foreach (XmlNode xNode in xDoc.DocumentElement.ChildNodes)
                {
                    CategoryXML cat = Convert2Category(xNode);
                    if (cat != null)
                        categories.Add(cat);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("List category ::", ex);
            }
            return categories;
        }

        private static IList<long> StringSub2SubList(string subs){
            
            IList<long> list = new List<long>();

            if (String.IsNullOrEmpty(subs)) return list;
            try
            {
                String[] arrs = subs.Split(',');

                foreach (string id in arrs)
                {
                    try
                    {
                        list.Add(Convert.ToInt64(id.Trim()));
                    }catch{}
                }
            }
            catch (Exception ex)
            {
                Logger.Error("StringSub2SubList", ex);
            }
            return list;
        }

        private static string SubList2StringSub(IList<long> subs)
        {
            string str = "";
            try
            {
                foreach (long id in subs)
                {
                    if (str.Length == 0)
                        str = id.ToString();
                    else
                        str += "," + id.ToString();
                }
            }
            catch (Exception ex)
            {
                Logger.Error("SubList2StringSub", ex);
            }
            return str;
        }

        

        private static CategoryXML Convert2Category(XmlNode xNode)
        {
            CategoryXML cat = null; ;
            try{
                cat = new CategoryXML(Convert.ToInt64(xNode.Attributes["id"].Value),
                               Convert.ToString(xNode.Attributes["name"].Value),
                               Convert.ToString(xNode.Attributes["description"].Value),
                               Convert.ToString(xNode.Attributes["url"].Value),
                               Convert.ToInt64(xNode.Attributes["parent"].Value),
                               StringSub2SubList( xNode.Attributes["subs"].Value));
            }
            catch(Exception ex)
            {
                Logger.Error("List XML ", ex);
            }


            return cat;
        }

        private static void LoadXML()
        {
            if (xDoc != null) return;
            xDoc = new XmlDocument();
            lock (xDoc)
            {
                xDoc.Load(categoryFilePath);               
                try
                {
                    HttpContext.Current.Cache.Add("Admin/Categories.xml", xDoc, new System.Web.Caching.CacheDependency(categoryFilePath), DateTime.Now.AddYears(1), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, new System.Web.Caching.CacheItemRemovedCallback(CacheRemoveCallback));
                }
                catch (Exception e)
                {
                    Logger.Error("Load file " + categoryFilePath, e);
                }
            }
        }

        private static void CacheRemoveCallback(string key, object obj, System.Web.Caching.CacheItemRemovedReason reason)
        {
            xDoc = null;
            LoadXML();
        }
        #endregion
    }
}
